iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Software Development

30天學會Golang系列 第 26

Day26 - Go的 gorm 資料庫處理

  • 分享至 

  • xImage
  •  

DBeaver 表的設定

今天的內容為使用者資料的寫入與讀取,會與 day23day24day25 有關,程式碼中也亦有註解

首先我們需要與資料庫互動,因此需要先定義資料庫與表,昨天我們有先新建一個資料庫:test_database,那今天我們就在這個 test_database 中新建一張表:user_table,新建方式可參照下圖

https://ithelp.ithome.com.tw/upload/images/20221007/20150797Ju57JKrbxL.png

新增表中欄位資訊的方式就是按滑鼠右鍵 新建 列,如下圖所示:
先新增三個欄位 id, email, password

  • id 建議設置成 int、自增 與 非空
  • email 建議設置成 varchar(100)
  • password 建議設置成 varchar(100)
  • 此外在約束欄位將 id 設置為 PRIMARY KEY

https://ithelp.ithome.com.tw/upload/images/20221007/20150797gHWWZVZxSh.png

設置好了後,表的部分就算是大功告成,接下來就是程式碼的部分

gorm 資料寫入與讀取

整體的結構如下圖所示:

https://ithelp.ithome.com.tw/upload/images/20221007/20150797yqyQCjWcK7.png

接下來的內容基本就是程式碼,詳情可參照註解,如果想複製貼上,請修改 import 內的路徑,或者可以考慮代碼連結,不過 go.mod 需要從這裡複製貼上

// go.mod
module it

go 1.19

require (
	github.com/gin-gonic/gin v1.8.1
	github.com/jinzhu/gorm v1.9.16
	github.com/joho/godotenv v1.3.0
)
// main.go
package main

import "it/day26/routers"

func main() {
	r := routers.InitRouter()

	// 定義在哪個 port 上執行
	r.Run(":8080")
}
// .env 隱私資料設定檔
DBUSER="root"
DBPASSWORD="1A2B3c4d"
DBHOST="127.0.0.1"
DBPORT="3306"
DBNAME="test_database"
// router.go 定義路徑
package routers

import (
	v1 "it/day26/routers/api/v1"

	"github.com/gin-gonic/gin"
)

func InitRouter() *gin.Engine {
	r := gin.Default()
	// 定義前端打的 api 路徑
	r.POST("/v1/register", v1.ApiRegister)
	r.POST("/v1/login", v1.ApiLogin)
	return r
}
// routers/api/model.go
package api

type User struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}
// api.go
package v1

import (
	"net/http"

	ctr "it/day26/app/controllers/user"
	api "it/day26/routers/api"

	"github.com/gin-gonic/gin"
)

// 如果是要給前端的 api,函式只能有一個輸入參
// 註冊使用者
func ApiRegister(c *gin.Context) {
	input := api.User{}
	c.Bind(&input)
	result := ctr.RegisterUser(input.Email, input.Password)
	template(c, http.StatusOK, result)
}

// 使用者登入
func ApiLogin(c *gin.Context) {
	input := api.User{}
	c.Bind(&input)
	result := ctr.LoginUser(input.Email, input.Password)
	template(c, http.StatusOK, result)
}

// 固定形式的輸出,有利於前端使用
func template(c *gin.Context, code int, data interface{}) {
	c.JSON(code, gin.H{
		"data": data,
	})
}
// const.go
package global

// 寫入資料庫的 表 名稱
const UserTable = "user_table"
// db.go
package database

import (
	"fmt"
	"log"
	"os"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	_ "github.com/joho/godotenv/autoload"
)

var db *gorm.DB

// init 為特別的函式,只會在程式初始化時執行一次
func init() {
	var err error
	db, err = gorm.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
		os.Getenv("DBUSER"),
		os.Getenv("DBPASSWORD"),
		os.Getenv("DBHOST")+":"+os.Getenv("DBPORT"),
		os.Getenv("DBNAME")))
	fmt.Println(os.Getenv("DBUSER"), ":", os.Getenv("DBPASSWORD"), "@tcp(", os.Getenv("DBHOST")+":"+os.Getenv("DBPORT"), ")/", os.Getenv("DBNAME"))

	if err != nil {
		log.Println(err)
	}
}

func CloseDB() {
	defer db.Close()
}

func Get() *gorm.DB {
	return db
}
// app/models/user/model.go
package user

type User struct {
	Email    string `gorm:"email"`
	Password string `gorm:"password"`
}
// app/models/user/hamdler.go
package user

import (
	"fmt"
	"it/day26/database"
	"it/day26/global"
)

// 新增資料
func CreateUser(email, password string) error {
	user := User{Email: email, Password: password}
	err := database.Get().Table(global.UserTable).Create(&user).Error
	return err
}

// 從資料庫找有沒有相對應的 email 與 password
func LoginUser(email, password string) error {
	user := User{Email: email, Password: password}
	err := database.Get().Table(global.UserTable).Where("email = ? and password = ?", email, password).Scan(&user).Error
	if err != nil {
		fmt.Println(err)
	}
	return err
}
// app/controllers/user/handler.go
package user

import User "it/day26/app/models/user"

// 註冊使用者
// 這邊可以重複註冊,如果不希望有重複的 email 出現,可在資料庫中設定 email 屬性為 unique
func RegisterUser(email, password string) bool {
	err := User.CreateUser(email, password)
	return err == nil
}

// 使用者登入
// 如果資料庫中沒有找到對應的使用者帳密,回傳 err = record not found,有找到則 err = nil
func LoginUser(email, password string) bool {
	err := User.LoginUser(email, password)
	return err == nil
}

新增使用者的結果如下:

https://ithelp.ithome.com.tw/upload/images/20221007/20150797VpDAOlBnQ8.png

https://ithelp.ithome.com.tw/upload/images/20221007/20150797GFfsKPdF2f.png

使用者登入情形:
正確:
https://ithelp.ithome.com.tw/upload/images/20221007/20150797kWeskifUjx.png
錯誤:
https://ithelp.ithome.com.tw/upload/images/20221007/20150797myYf751LtZ.png

第26天報到,好趕@@

代碼連結

https://github.com/luckyuho/ithome30-golang/tree/main/day26


上一篇
Day25 - Go的 gorm 資料庫處理 - DBeaver
下一篇
Day27 - Go的 jwt 解說
系列文
30天學會Golang31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言